package jadeCW.behaviour;

import jade.core.behaviours.CyclicBehaviour;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jadeCW.PatientAgent;
import jadeCW.output.Printer;

/**
 * Respond To Proposal 1 behaviour class
 * 
 * @author br08, dac108, dv08
 */
public class RepondToProposal1 extends CyclicBehaviour {
	/**
	 * Generated serialisation ID
	 */
	private static final long serialVersionUID = -449916307829308375L;

	@Override
	public void action() {
		// must be run on a patient
		if (!(myAgent instanceof PatientAgent)) {
			return;
		}

		PatientAgent patient = (PatientAgent) myAgent;

		// create the template to response to proposals
		MessageTemplate template = MessageTemplate.and(MessageTemplate
				.MatchPerformative(ACLMessage.REQUEST), MessageTemplate
				.MatchConversationId(ProposeSwap.TYPE));

		// receive a message
		ACLMessage message = patient.receive(template);

		// if no message received, block and try again
		if (message == null) {
			block();
			return;
		}
		
		// get the offered and desired appointments
		String content = message.getContent();
		String[] appointments = content.split("-");
		
		int offeredAppointment = Integer.parseInt(appointments[0]);
		int desiredAppointment = Integer.parseInt(appointments[1]);
		
		Printer.printRTP1Receive(patient, offeredAppointment, message.getSender());

		// create a reply
		ACLMessage reply = message.createReply();

		// if the offered appointment is worse, the patient can't accept or
		// doesn't own the appointment, reject
		if (patient.isOfferedWorse(offeredAppointment) || patient.getAppointment() != desiredAppointment) {

			reply.setPerformative(ACLMessage.REJECT_PROPOSAL);
			
			Printer.printRTP1SendReject(patient, offeredAppointment, desiredAppointment, message.getSender());

		} else if (patient.isRequesting()) {

			// if this patient is current requesting something itself and cannot
			// respond, refuse the request temporarily
			reply.setPerformative(ACLMessage.REFUSE);
			
			
			Printer.printRTP1SendRefuse(patient, offeredAppointment, desiredAppointment, message.getSender());

		} else {

			// accept as offer equal or better and can accept it
			reply.setPerformative(ACLMessage.ACCEPT_PROPOSAL);
			
			Printer.printRTP1SendAccept(patient, offeredAppointment, desiredAppointment, message.getSender());

			// create inform message
			ACLMessage inform = new ACLMessage(ACLMessage.INFORM);

			// inform all know hospitals
			for (DFAgentDescription hospital : patient
					.getAppointmentAllocators()) {
				inform.addReceiver(hospital.getName());
			}

			// inform with the appointment to swap to
			inform.setContent(String.valueOf(offeredAppointment));
			inform.setConversationId(UpdateAppointments.TYPE);
			inform.setReplyWith(UpdateAppointments.TYPE + System.currentTimeMillis());

			Printer.printInformSend(patient, offeredAppointment);
			
			// send the inform message
			patient.send(inform);
			
			// update parent patient with new appointment
			patient.setAppointment(offeredAppointment);
		}

		// send the reply
		patient.send(reply);
	}
}